package com.uow.algdemo.animation;

import java.util.List;

import com.uow.algdemo.ui.R;

import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.widget.ImageView;
import android.widget.RelativeLayout;
/**
 * This class will receive data of the queen problem and back tracking algorithm animation steps, then generate animation on animation layout.
 */
public class AnimationQueen extends RelativeLayout implements AnimationInterface
{
	/**
     * This is handler for whole progress of animation.
     */
	private Handler handler;
	/**
     * This array contains view of check board.
     */
	private ImageView[][] iv;
	/**
     * This is current status of animation completed or not.
     */
	private boolean finished = false;
	/**
     * This is current status of pause or running.
     */
	private boolean pause = false;
	/**
     * This array contains steps of the queen problem solution animation.
     */
	private List<int[][]> steps;
    /**
     * This is the current step of animation position.
     */
	private int position = 0;
    /**
     * This is the current speed of animation.
     */
	private int speed = 10;
    /**
     * This is the number of queens for this problem.
     */
	private int total;
	/**
     * @param context The Context the view is running in, through which it can access the current theme, resources, etc.
     * @param newSteps Steps of the queens problem solution animation.
     * @param n Numbers of queens.
     * @param width Width of layout in pixel.
     * @param height Height of layout in pixel.
     */
	public AnimationQueen(Context context, List<int[][]> newSteps, int n, int width, int height)
	{
        super(context);
		steps = newSteps;
		total = n;
        iv = new ImageView[total][total];
        for(int row = 0; row < total; row++)
        {
            for(int col = 0; col < total; col++)
            {
                iv[row][col] = new ImageView(context);
                if(row%2==0)
                {
	                if(col%2==0)
	                	iv[row][col].setBackgroundResource(R.drawable.ic_blank);
	                else
	                	iv[row][col].setBackgroundResource(R.drawable.ic_black);
                }
                else
                {
	                if(col%2==0)
	                	iv[row][col].setBackgroundResource(R.drawable.ic_black);
	                else
	                	iv[row][col].setBackgroundResource(R.drawable.ic_blank);
                }
        		RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(50, 50);
        		params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
        		params.bottomMargin = ((height - 400) / 2 + 400 ) - row * 50;
        		params.leftMargin = ((width - (total * 50)) / 2 ) + (col * 50);
        		this.addView(iv[row][col],params);
            }
        }
	}
	/**
	 * @param steps The steps to set
	 */
	public void setSteps(List<int[][]> newSteps)
	{
		steps = newSteps;
	}
	/**
	 * @return The status
	 */
	public boolean getStatus()
	{
		return finished;
	}
	/**
	 * @return The speed
	 */
	public int getSpeed()
	{
		return speed;
	}
    /**
     * This method set speed of animation.
     * @param newSpeed Speed value to set.
     */	
	public void setSpeed(int newSpeed)
	{
		speed = newSpeed;
	}
    /**
     * This method send feedback from this class for different command.
     * @param mes Message to current class.
     * @return An array for feedback information.
     */
	public int[][] sendMessage(int mes)
	{
		return null;
	}
	/**
     * This method generate animation and start animation.
     */	
	@SuppressLint("HandlerLeak")
	public void runAnimation()
	{
		handler = new Handler()
		{
			public void handleMessage(Message msg)
			{
				switch (msg.what)
				{
					case 1:
					{
						if(pause == false && finished == false)
						{
							if(position < steps.size())
							{
								int[][] a = steps.get(position);
								if(a[0][0] == 0)
								{
									place(a[1][0],a[1][1]);
								}
								else if(a[0][0] == 1)
								{
									delete(a[1][0],a[1][1]);
								}
								position++;
							}
							else
							{
								finished = true;
							}
						}
						break;
					}
				}
				super.handleMessage(msg);
			}
		};
		handler.sendEmptyMessage(1);
	}

    /**
     * This method pause animation.
     */	
	public void pauseAnimation()
	{
		pause = true;
	}

    /**
     * This method resume animation from pause position.
     */	
	public void resumeAnimation()
	{
		pause = false;
    	handler.sendEmptyMessage(1);
	}

    /**
     * This method stop animation and clear layout.
     */	
	public void stopAnimation()
	{
		finished = true;
	}
    /**
     * This method show next step of animation when animation is pause.
     */	
	public void nextStep()
	{
		if(pause)
		{
			if(position < steps.size())
			{
				int[][] a = steps.get(position);
				if(a[0][0]==0)
				{
					place(a[1][0],a[1][1]);
				}
				else
				{
					delete(a[1][0],a[1][1]);
				}
				position++;
			}
		}
	}
    /**
     * This method show last step of animation when animation is pause.
     */	
	public void lastStep()
	{
		if(pause)
		{
			if(position > 0)
			{
				position--;
				int[][] a = steps.get(position);
				if(a[0][0]==0)
				{
					delete(a[1][0],a[1][1]);
				}
				else
				{
					place(a[1][0],a[1][1]);
				}
			}
		}
	}
    /**
     * This method generate animation for place a queen on chess board.
     * @param x Coordinate of horizontal.
     * @param y Coordinate of vertical.
     */
	private void place(int x, int y)
	{
		iv[x][y].setImageResource(R.drawable.ic_queen);
    	handler.sendEmptyMessageDelayed(1, speed * 50);
	}
    /**
     * This method generate animation for delete a queen from chess board.
     * @param x Coordinate of horizontal.
     * @param y Coordinate of vertical.
     */
	private void delete(int x, int y)
	{
    	iv[x][y].setImageResource(R.drawable.ic_none);
    	handler.sendEmptyMessageDelayed(1, speed * 50);
    }
}
